/*
 * Created on Feb 19, 2004
 *
 * Author: Sandeep Prakash
 * Project: Sucxentv2 (using leaf nodes only)
 */
// this class has methods to insert information into the database
package dbsucxentW.storageW.loadersW.relationalW;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.File;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.Connection;
import dbsucxentW.storageW.loadersW.Store;
import dbsucxentW.constantW.Constant;
import dbsucxentW.storageW.parserW.DocumentSummary;

/**
 * @author Administrator
 *
 * 
 */
public class RelationalStore extends Store {

    private Connection _dbConnection;
    long t1;
    //bulk loader 
    protected BufferedWriter _writers[];
    private String _dbName;
    // added by zhouyong
    // @17/12/2007
    private String dataSourceName;

    /**
     * Constructor. Set JdbcURLProvider as URL format etc.. differ
     * and so do some syntax aspects.
     */
    public RelationalStore( 
            Connection dbConnection, 
            String dbName, 
            String file,
            String dataSourceName) {
        super();
        _dbConnection = dbConnection;
        _dbName = dbName;		//klarinda 20060905
        _file = file;
        this.dataSourceName = dataSourceName;
        createFiles(); // bulk loader	
        try {
            _docId = generateNextDocId();
            
        } catch (Exception e) {
            System.out.println("RelationalStore: error at generating docId!");
            System.out.println(e.getMessage());
        }

    }

    @Override
    public void store(DocumentSummary summary) throws Exception {
        this._summary = summary;
        storeDocId();
        storeDocRValue();
        commit();
    }

    private String getTableName(int tableId){
        String name = Constant.TABLE_NAMES[tableId];
        return (dataSourceName == null)?name:dataSourceName + "_" + name;
    }
    
    /**
     * Generate the next document ID for the input document
     * value.
     * @return The next document ID
     */
    private int generateNextDocId() throws Exception {
        Statement _stmt = _dbConnection.createStatement();
        ResultSet rs = _stmt.executeQuery("SELECT MAX(Id) FROM " + this.getTableName(Constant.DOCUMENT_TABLE));
        int nextDocId;
        if (rs.next()) {
            nextDocId = rs.getInt(1) + 1;
        } else {
            nextDocId = 0;
        }
        rs.close();
        _stmt.close();
        return nextDocId;
    }

    /**
     * Stores the document ID to file for bulk insert
     */
    private void storeDocId() {
        try {	//write the row to file for bulk load
            _writers[Constant.DOCUMENT_TABLE].append(_docId + "\t" + _file);
            _writers[Constant.DOCUMENT_TABLE].newLine();
        } catch (IOException e) {
            System.out.println("ERR at bulk load DocId");
            System.out.println(e.getMessage());
        }
    }

    private void storeDocRValue() throws Exception {
        t1 = System.currentTimeMillis();

        int maxDepth = _summary.getMaxDepth();

        String row; //klarinda 20060904

        for (int i = 0; i < maxDepth; i++) {
            row = _docId + "\t" + (i + 1) + "\t" + ((_summary.getRValue(i + 1) - 1) / 2 + 1)
                    + "\t" + _summary.getAncestorValue(i + 1);
            try {
                _writers[Constant.DOCRVALUE_TABLE].append(row);
                _writers[Constant.DOCRVALUE_TABLE].newLine();
            } catch (IOException e) {
                System.out.println("ERR at bulk load DocumentRValue");
                System.out.println(e.getMessage());
            }
        }
    }

    @Override
    public void storePath(int pathId, String path) {
        try {
            _writers[Constant.PATH_TABLE].append(pathId + "\t" + path);
            _writers[Constant.PATH_TABLE].newLine();
        } catch (IOException e) {
            System.out.println("ERR at bulk load Path");
            System.out.println(e.getMessage());
        }
    }

    private void createFiles() {
        String fname;
        _writers = new BufferedWriter[Constant.NO_OF_TABLES];

        //only create DOC, RVALUE, PATH file
        try {
            // add by erwin  2007-07-04
            //File dir1 = new File(".");
            //Constant.BULKFILEPATH = "D:\\bulk\\";
            
            Constant.BULKFILEPATH = controller.Controller.BULK_PATH;

            fname = Constant.BULKFILEPATH + getTableName(Constant.DOCUMENT_TABLE) + ".tbl";
            _writers[Constant.DOCUMENT_TABLE] = new BufferedWriter(new FileWriter(fname));

            fname = Constant.BULKFILEPATH + getTableName(Constant.DOCRVALUE_TABLE) + ".tbl";
            _writers[Constant.DOCRVALUE_TABLE] = new BufferedWriter(new FileWriter(fname));

            fname = Constant.BULKFILEPATH + getTableName(Constant.PATH_TABLE) + ".tbl";
            _writers[Constant.PATH_TABLE] = new BufferedWriter(new FileWriter(fname));
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    //klarinda 20060905 load tables into db
    public void commit() throws Exception {
        //k20070525 add TextContent & AttrContent

        String fname, sql;
        String db = "\"" + _dbName + "\"";

        try {
            _writers[Constant.DOCUMENT_TABLE].flush();
            _writers[Constant.DOCUMENT_TABLE].close();
            _writers[Constant.DOCRVALUE_TABLE].flush();
            _writers[Constant.DOCRVALUE_TABLE].close();
            _writers[Constant.PATH_TABLE].flush();
            _writers[Constant.PATH_TABLE].close();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }

        for (int x = 0; x < Constant.NO_OF_TABLES; x++) {

            try {
                fname = Constant.BULKFILEPATH + getTableName(x) + ".tbl";

                sql = "USE master;\n";
                sql += "ALTER DATABASE " + db + " SET RECOVERY BULK_LOGGED \n";
                sql += "USE " + db + ";\n";
                sql += "BULK INSERT " + getTableName(x) + " \n";
                sql += "FROM '" + fname + "'\n";

                if (x == Constant.DOCUMENT_TABLE) {
                    sql += "WITH (ORDER(Id), TABLOCK);\n";
                } else if (x == Constant.DOCRVALUE_TABLE) {
                    sql += "WITH (ORDER(DocId,Level), TABLOCK);\n";
                } else if (x == Constant.PATH_TABLE) {
                    sql += "WITH (ORDER(PathId), TABLOCK);\n";
                } else if (x == Constant.PATHVALUE_TABLE || x == Constant.TEXTCONTENT_TABLE) {
                    sql += "WITH (ORDER(DocId,AncestorDeweyGroup DESC), TABLOCK);\n";
                } else if (x == Constant.ATTRIBUTE_TABLE || x == Constant.ATTRCONTENT_TABLE) {
                    sql += "WITH (ORDER(DocId,AncestorDeweyGroup), TABLOCK);\n";
                }

                sql += "USE master;\n";
                sql += "ALTER DATABASE " + db + " SET RECOVERY FULL;\n";
                System.out.println(sql);
                System.out.println();

                Statement _stmt = _dbConnection.createStatement();
                _stmt.execute(sql);
                _dbConnection.commit();
                _stmt.close();

            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }

        sql = "USE " + db + ";\n";
        Statement _stmt = _dbConnection.createStatement();
        _stmt.execute(sql);
        _dbConnection.commit();
        _stmt.close();
    }
}
